package com.easylinkin.linkappapi.webcammanage.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.webcammanage.entity.BindDeviceParams;
import com.easylinkin.linkappapi.webcammanage.entity.DeviceAttributeStatus;
import com.easylinkin.linkappapi.webcammanage.entity.EnterpriseVideoTreeQueryDTO;
import com.easylinkin.linkappapi.webcammanage.mapper.DeviceAreaHandlerMapper;
import com.easylinkin.linkappapi.webcammanage.service.DeviceAreaHandlerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * class info :
 *
 * @author 刘启航
 * @date 2021/4/20 10:53
 */
@Service
@Slf4j
public class DeviceAreaHandlerServiceImpl extends ServiceImpl<DeviceAreaHandlerMapper, Device> implements DeviceAreaHandlerService {

    @Value("${edu.apiUrl:http://localhost:15004/api}")
    private String apiUrl;

    private RestTemplate restTemplate = new RestTemplate();

    @Override
    public IPage<Device> getUnassociatedAreaDevicesPage(Page page, Device device) {
        List<Device> list = baseMapper.selectUnBindDevices(page, device);
        setAreaName(list);
        page.setRecords(list);
        return page;
    }

    /**
     * 查询所有的，所有租户下的，如果device.tenantId=null
     *
     * @param page
     * @param device
     * @return
     */
    @Override
    public IPage<DeviceAttributeStatus> getDeviceVideoList(Page page, Device device) {
        List<DeviceAttributeStatus> list = baseMapper.getVideoTypeDeviceListGlobal(page, device);
        if (list == null || list.size() <= 0) {
            page.setTotal(0);
            page.setRecords(null);
            return page;
        }

        Set<String> deviceIds = list.stream().map(DeviceAttributeStatus::getId).collect(Collectors.toSet());
        List<DeviceAttributeStatus> videoInfoByDevice = baseMapper.getVideoInfoByDeviceGlobal(null, deviceIds);
        Map<String, List<DeviceAttributeStatus>> res = videoInfoByDevice.stream().collect(Collectors.groupingBy(DeviceAttributeStatus::getId));
        for (DeviceAttributeStatus deviceAttributeStatus : list) {
            deviceAttributeStatus.setChildAttributeList(res.get(deviceAttributeStatus.getId()));
        }
        page.setRecords(list);
        return page;
    }

    @Override
    public IPage<DeviceAttributeStatus> getEnterpriseVideoList(Page page, Device device) {
        IPage<DeviceAttributeStatus> res = getDeviceVideoList(page, device);
        return res;
    }

    @Override
    public List<Map> getEnterpriseVideoTree(EnterpriseVideoTreeQueryDTO enterpriseVideoTreeQueryDTO) {
        Device device = new Device();
        String projectNameSearch = enterpriseVideoTreeQueryDTO.getProjectName();
        if (projectNameSearch != null) {
            projectNameSearch = projectNameSearch.trim();
        }
        device.setProjectName(projectNameSearch);
        List<DeviceAttributeStatus> deviceAttributeStatuses = getEnterpriseVideoList(new Page(0, -1), device).getRecords();
        log.info("deviceAttributeStatuses:{}", deviceAttributeStatuses);
        Map<String, List<DeviceAttributeStatus>> projectName2DeviceAttrListMap = new HashMap<>(16);
        Map<String, List<DeviceAttributeStatus>> onlineMap = new HashMap<>(16);
        if (!ObjectUtils.isEmpty(deviceAttributeStatuses)) {
            projectName2DeviceAttrListMap = deviceAttributeStatuses.stream().filter(deviceAttributeStatus -> ObjectUtils.isNotEmpty(deviceAttributeStatus.getProjectName())).collect(Collectors.groupingBy(DeviceAttributeStatus::getProjectName));
            onlineMap = deviceAttributeStatuses.stream().filter(deviceAttributeStatus ->
                            ObjectUtils.isNotEmpty(deviceAttributeStatus.getProjectName()))
                    .filter(deviceAttributeStatus -> deviceAttributeStatus.getOnlineState() != null && deviceAttributeStatus.getOnlineState().equals(1))
                    .collect(Collectors.groupingBy(DeviceAttributeStatus::getProjectName));
        }

        HttpHeaders headers = getDefaultHeader();
        HttpEntity httpEntity = new HttpEntity<>(new JSONObject(), headers);
        JSONObject res = restTemplate.postForObject(apiUrl + "/enterpriseOpenApi/organization/listProjectTree",
                httpEntity, JSONObject.class);
        Object data = res.get("data");
        if (data != null) {
            List<Map> res2 = (List<Map>) data;
            log.info("res2:{}", res2);
            for (Map obj : res2) {
                setVideoList(projectName2DeviceAttrListMap, onlineMap, obj, 0, 0, enterpriseVideoTreeQueryDTO.getProjectName());
            }
            for (Iterator<Map> iterator = res2.iterator(); iterator.hasNext(); ) {
                Map obj = iterator.next();
                // 此处删去的是 组织下没有项目的组织
                if (ObjectUtils.isNotEmpty(projectNameSearch) && (obj == null || ObjectUtils.isEmpty(obj.get("projects")) && ObjectUtils.isEmpty(obj.get("children")))) {
                    iterator.remove();
                }
            }
            return res2;
        }
        return null;
    }

    private Map<String, Object> setVideoList(Map<String, List<DeviceAttributeStatus>> projectName2DeviceAttrListMap, Map<String, List<DeviceAttributeStatus>> onlineMap, Map obj, int totalVideoCount, int onlineVideoCount,String projectNameSearch) {
        Map<String, Object> result = new HashMap(4);
        List<Map> proejcts = (List<Map>) obj.get("projects");
        if (projectNameSearch != null) {
            projectNameSearch = projectNameSearch.trim();
        }
        if (ObjectUtils.isNotEmpty(proejcts)) {
            for (Iterator<Map> iterator = proejcts.iterator(); iterator.hasNext(); ) {
                Map proejct = iterator.next();
                String projectName = (String) proejct.get("name");
                if (projectName != null) {
                    if (ObjectUtils.isNotEmpty(projectNameSearch) && projectNameSearch.trim().length() != 0 && !projectName.contains(projectNameSearch)) {
                        iterator.remove();
                    }
                    List<DeviceAttributeStatus> videoList = projectName2DeviceAttrListMap.get(projectName);
                    if (ObjectUtils.isNotEmpty(videoList)) {
                        proejct.put("videoList", videoList);
                        proejct.put("totalVideoCount", videoList.size());
                        totalVideoCount += videoList.size();
                        List<DeviceAttributeStatus> onlineVideoList = onlineMap.get(projectName);
                        if (ObjectUtils.isNotEmpty(onlineVideoList)) {
                            proejct.put("onlineVideoCount", onlineVideoList.size());
                            onlineVideoCount += onlineVideoList.size();
                        } else {
                            proejct.put("onlineVideoCount", 0);
                        }
                    }
//                    else {
//                        //删去 没有摄像头的项目
////                        iterator.remove();
//                    }
                }
            }
        }
        List<Map> children = (List<Map>) obj.get("children");
        if (ObjectUtils.isNotEmpty(children)) {
            for (Iterator<Map> iterator = children.iterator(); iterator.hasNext(); ) {
                Map child = iterator.next();
                Map<String, Object> resultSub = setVideoList(projectName2DeviceAttrListMap, onlineMap, child, 0, 0,projectNameSearch);
                Integer subtotalVideoCount = (Integer) resultSub.get("totalVideoCount");
                totalVideoCount += subtotalVideoCount;
                if (ObjectUtils.isNotEmpty(resultSub.get("onlineVideoCount"))) {
                    Integer subonlineVideoCount = (Integer) resultSub.get("onlineVideoCount");
                    onlineVideoCount += subonlineVideoCount;
                }
                if (ObjectUtils.isNotEmpty(projectNameSearch) && (ObjectUtils.isEmpty(child.get("projects")) && ObjectUtils.isEmpty(child.get("children")))) {
                    // 删去没有项目的组织
                    iterator.remove();
                }
            }
        }
        obj.put("totalVideoCount", totalVideoCount);
        obj.put("onlineVideoCount", onlineVideoCount);
        result.put("totalVideoCount", totalVideoCount);
        result.put("onlineVideoCount", onlineVideoCount);
        return result;
    }

    private HttpHeaders getDefaultHeader() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.set("Accept", "application/json");
        return headers;
    }

    @Override
    public Integer getDeviceVideoCount(Device device) {
        Integer total = baseMapper.getDeviceVideoCount(device);
        if (total == null) {
            return 0;
        }
        return total;
    }

    @Override
    public void unBindDevice(List<BindDeviceParams> deviceList) {
        if (deviceList.size() <= 0) {
            log.info("解绑设备ID 长度<=0");
            return;
        }
        List<String> idList = deviceList.stream().map(BindDeviceParams::getId).collect(Collectors.toList());
        baseMapper.unBindDevice(idList);
    }

    @Override
    public Boolean bindDevice(List<BindDeviceParams> deviceList) {
        if (deviceList.size() <= 0) {
            log.info("绑定数据参数 长度<=0");
            return false;
        }
        for (BindDeviceParams bdp :
                deviceList) {
            if (StringUtils.isEmpty(bdp.getId()) || StringUtils.isEmpty(bdp.getAreaId())) {
                log.info("绑定数据参数错误不能包含空值");
                return false;
            }
        }
        baseMapper.bindDevice(deviceList);
        return true;
    }


    private void setAreaName(List<Device> list) {
        if (list != null) {
            list.forEach(d -> {
                if (StringUtils.equals(d.getSpaceId(), d.getAreaId())) {
                    d.setAreaName(null);
                    d.setAreaPath(null);
                }
            });
        }
    }
}
